﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatterns.CommandPatterns
{
    class CommandPattern
    {
        static void Main(string[] args)
        {
            //行为不具备原子性时，可以让调用者与接收者解耦
            //命令非常容易扩展
            //缺点依然是，行为过多时，命令会膨胀地很厉害，得慎重考虑
            Invoker invoker = new Invoker();

            Receiver re1 = new ConcreteReciver1();
            Receiver re2 = new ConcreteReciver2();

            Command cm1 = new ConcreteCommand1(re1);
            Command cm2 = new ConcreteCommand2(re1, re2);
            //执行单执行者命令
            invoker.setCommand(cm1);
            invoker.action();
            //执行多执行者命令
            invoker.setCommand(cm2);
            invoker.action();
        }
    }

    /// <summary>
    /// 命令接收者抽象类
    /// </summary>
    public abstract class Receiver {
        public abstract void doSomething();
    }

    /// <summary>
    /// 命令接收者1
    /// </summary>
    public class ConcreteReciver1 : Receiver
    {
        public override void doSomething()
        {
        }
    }

    /// <summary>
    /// 命令接收者2
    /// </summary>
    public class ConcreteReciver2 : Receiver
    {
        public override void doSomething()
        {
        }
    }

    /// <summary>
    /// 命令抽象类
    /// </summary>
    public abstract class Command {
        public abstract void execute();
    }
    /// <summary>
    /// 命令1
    /// </summary>
    public class ConcreteCommand1 : Command
    {
        private Receiver receiver;

        public ConcreteCommand1(Receiver _receiver) {
            this.receiver = _receiver;
        }
        public override void execute()
        {
            this.receiver.doSomething();
        }
    }
    /// <summary>
    /// 命令2
    /// </summary>
    public class ConcreteCommand2 : Command
    {
        private Receiver receiver1;
        private Receiver receiver2;

        public ConcreteCommand2(Receiver _receiver1, Receiver _receiver2)
        {
            this.receiver1 = _receiver1;
            this.receiver2 = _receiver2;
        }
        public override void execute()
        {
            this.receiver1.doSomething();
            this.receiver2.doSomething();
        }
    }

    public class Invoker {
        private Command command;

        public void setCommand(Command _command) {
            this.command = _command;
        }

        public void action() {
            this.command.execute();
        }
    }
}
